package agentsSME;


import java.util.Random;

import main.BuildModel;
import enviornment.Clock;
import repast.simphony.engine.environment.RunEnvironment;
import repast.simphony.engine.schedule.ActionQueue;
import repast.simphony.engine.schedule.IAction;
import repast.simphony.engine.schedule.ISchedulableAction;
import repast.simphony.engine.schedule.ISchedule;
import repast.simphony.engine.schedule.PriorityType;
import repast.simphony.engine.schedule.Schedule;
import repast.simphony.engine.schedule.ScheduleGroup;
import repast.simphony.engine.schedule.ScheduleParameters;
import repast.simphony.engine.schedule.ScheduledMethod;
import repast.simphony.essentials.RepastEssentials;

/**
 * Represents behaviours that a SME agent has. 
 * @author Chunhui Li
 *
 */

public class BehaviourSME implements IAction {
	private SME sme;
    private String behaviour;
    private double duration;
    private boolean isDone;
    private boolean isPaused; 
    private double priority;
    private boolean inProgress;
    private double task; // Each behaviour is behaved to complete a task, this can be set during the run of simulation
    private double executedTime;
    private double end_time;
    private double start_time;
    private double hours_of_work;
    private int allocatedEmployees;
    private boolean isEmergent;
    private boolean shared;
    private int code;
    private String type;
    private double impactFactor;
    private double task_amount;
    
    private Random random=new Random();

    /**
     * The constructor of a behaviour. 
     * @param sme the SME which has this behaviour.
     * @param behaviour the name of the behaviour.
     * @param priority the priority that this behaviour gets executed in Repast
     * @param duration the duration (in ticks) of this behaviour last for when it is triggered. It includes the night time
     * when employees are not off-work.
     */
	public BehaviourSME(SME sme, String behaviour, double priority, double task, boolean emergency, int code, String type, boolean shared) {
		isEmergent= emergency;
		this.shared=shared;
		this.sme = sme;
	    this.behaviour = behaviour;
		this.duration = 0.0;
		this.priority = priority;
		isDone = false;
		inProgress = false;
		isPaused=false;
		this.task = task;
		executedTime = 0.0;
		start_time = 0.0;
		end_time = 0.0;
		allocatedEmployees = 0;
		hours_of_work=0.0;
		this.code=code;
		impactFactor = 0.0;
		this.type=type;
		task_amount = task; //This will not be changed in the simulation
	}
	/*
	public BehaviourSME(String behaviour){
		 this.behaviour = behaviour;
	}*/
	public double setTaskStats(double min, double max){
		
		//task= random.nextInt((int)(max-min))+(int)min; //Original idea
		double x=(max-min)*BuildModel.TICK_PER_HOUR;
		double task_random=(random.nextInt(((int)x))+1.0)+min*BuildModel.TICK_PER_HOUR;
		return task_random; //in ticks
	}
	public String getType(){
		return type;
	}
	public void setType(String s){
		type=s;
	}
	public void setShared(boolean b){
		shared=b;
	}
	public boolean getShared(){
		return shared;
	}
	public double getTaskAmount(){
		return task_amount;
	}
	public double getStartTime(){
		return start_time;
	}
	public double getPriority(){
		return priority;
	}
	public double getTask(){
		return task;
	}
	public double getExecutedTime(){
		return executedTime;
	}
	public double getEndTime(){
		return end_time;
	}
	public String getBehaviourName(){
		return behaviour;
	}
	public double getDuration(){
		return duration;
	}
	public int getResources(){
		return allocatedEmployees;
	}
	public double getHourOfWork(){
		return hours_of_work;
	}
	public int getCode(){
		return code;
	}
	public void setCode(int x){
		code=x;
	}
	public void setHoursOfWork(double d){
		hours_of_work=d;
	}
	public void setDuration(double d){
		this.duration = d;
	}
	public void setResources(int number){
		allocatedEmployees= number;
	}
	public void setTask(double t){
		this.task = t;
	}
	public void setExecutionT(double t){
		executedTime = t;
	}
	public void setEndTime(double t){
		end_time = t;
	}
	public void setStartTime(double t){
		start_time = t;
	}
	public void setPriority(double p){
		this.priority = p;
	}
	public void setBname(String s){
		this.behaviour =s;
	}
    
    public boolean isDone(){
    	return isDone;
    }
    
    public boolean isInProgress(){
    	return inProgress;
    }
    public boolean isPaused(){
    	return isPaused;
    }
    public void setPause(boolean p){
    	isDone = p;
    }
    public void setDone(boolean done){
    	isDone = done;
    }
    
    public void setProgress(boolean b){
    	inProgress =b;
    }
    public boolean isEmergent() {
		return isEmergent;
	}
	public void setEmergent(boolean isEmergent) {
		this.isEmergent = isEmergent;
	}
	public double getImpactFactor(){
		return impactFactor;
	}
	public void setImpactFactor(double f){
		impactFactor = f;
	}

    /**
     * calculates the remaining task of a behaviour by current time 
     * @param current
     */
    public double remainTask(double current){
    	Clock c1 = new Clock();
    	Clock c2 = new Clock();
    	c1.convertTicks(current);
    	c2.convertTicks(executedTime);
    	double hours = c1.SubtractionToWorkingHours(c1, c2);
    	System.out.println("---------"+c1.toString()+"-"+c2.toString()+"="+hours
    			+"working hours");
    	double remain = task - allocatedEmployees*hours* BuildModel.TICK_PER_HOUR;
    	if(c1.getDay()==c2.getDay()){
    		remain = task - allocatedEmployees*(current-executedTime);	
    	}
    	System.out.println("---------"+this.getBehaviourName()+" remains "+remain+" ticks; "+ current+ " - "+executedTime);
    	return remain;
    }
    
	@Override	
	public void execute() {
		setProgress(true);
		setExecutionT(RepastEssentials.GetTickCount());
		System.out.println("------"+getBehaviourName()+" "+ sme.companyName+": This behaviour is executed at Tick " + RepastEssentials.GetTickCount());
		System.out.println("------Duration of this behaviour: " + duration +"------task: "+ getTask());
	}
	
	public String toString(){
		String s = this.behaviour +" is started at Tick "+ this.executedTime+" and finished at Tick "+ this.end_time;
				
		return s;
	}
	public String toStringService(){
		String s = this.behaviour +" is started at Tick "+ this.start_time+" and finished at Tick "+ this.end_time;
		return s;
	}
	
}
